#include "../common.h"

const uint8_t _mp3_tx = GPIO_NUM_17;
const uint8_t _mp3_rx = GPIO_NUM_16;
const int _packet_len = 10;
const uint16_t _mp3_interval = 2000;
class MiniMp3Wrap {
public:
	int body = 0;
	int cmd;AIGC_JSON_HELPER(cmd,body)
};

cmd_injection_handle(MINI_MP3, cmd_mini_mp3,MiniMp3Wrap *ctx,MiniMp3Wrap) {
	App.pMiniMp3Service->send(ctx->cmd, ctx->body);
}
size_t MiniMp3Service::decodePacket(uint8_t *packet, size_t recount) {
	//1 一直读包头
	//2 读剩余包
	//3 包尾
	//4 校验
	//5 内容解码
	//socket/file 连接资源
	if (this->serial->available() <= 0) {
		return recount;
	}
	//可能会出现数据断流，断流要重新接上上一次数据
	while (this->serial->available() > 0) {
		//1 一直读包头
		if (recount == 0) { //断流情况 用recount是否为0 不为0说明不用读头
			recount = this->serial->read(packet, 3);
			//检查包头是否合非
			if (recount != 3) {
				recount = 0;
				continue;
			}
			if (packet[0] != 0x7E || packet[1] != 0xFF || packet[2] != 0x06) {
				recount = 0;
				continue;
			}
		}
		//2 读剩余包
		//read方法里不会改变外面的数组指针
		size_t surplus = _packet_len - recount;
		size_t add = this->serial->read(packet + recount, surplus);
		recount += add;
		if (add != surplus) { //出现断流
			continue;
		}
		//3 包尾
		if (packet[_packet_len - 1] != 0xEF) {
			recount = 0;
			continue;
		}

		//4 校验
		uint16_t sum = 0;
		for (int i = 1; i < 7; i++) {
			sum += packet[i];
		}
		sum = 0 - sum;
		//取得校验码 跟重新算出来的校验码对比
		if (sum != (packet[7] << 8 | packet[8])) {
			recount = 0;
			continue;
		}
		//5 内容解码
		return recount;
	}
	return recount;
}
// 7E FF 06 0F 00 01 01 xx xx EF
// 0	->	7E is start code
// 1	->	FF is version
// 2	->	06 is length
// 3	->	0F is command
// 4	->	00 is no receive
// 5~6	->	01 01 is argument
// 7~8	->	checksum = 0 - ( FF+06+0F+00+01+01 )
// 9	->	EF is end code
//经测过，如果播放文件比较大，要等十秒左右才有反应
void MiniMp3Service::send(uint8_t cmd, uint16_t body) {
	if (this->serial == nullptr)
		return;
	long t = millis() - this->lastSend;
	if (_mp3_interval > t) {
		delay(_mp3_interval - t);
	}
	char buff[40];
	sprintf(buff, "currCpu : %d, Mp3 : cmd : %d ,body: %d", xPortGetCoreID(), cmd, body);
	LOG_DEBUG(buff)
	uint8_t b1 = 0;
	uint8_t b2 = 0;
	if (body > 0) {
		b1 = static_cast<uint8_t>((body & 0xff00) >> 8); //5
		b2 = static_cast<uint8_t>(body & 0x00ff); //6
	}
	uint8_t packet[_packet_len] = {	//
					0x7E, // 0
							0xFF, //1
							0x06, //2
							cmd, //3
							00, //4
							b1, //5
							b2, //6
							00, 00, //检验码 7 8
							0xEF // 9
					};

	//cal
	uint16_t sum = 0;
	for (int i = 1; i < 7; i++) {
		sum += packet[i];
	}
	sum = 0 - sum;
	packet[7] = ((sum & 0xff00) >> 8);
	packet[8] = (sum & 0xff);

	this->serial->write(packet, _packet_len);
	this->lastSend = millis();

//	while (this->serial->read() != 0x7E) {
//	}
//
//	uint8_t ack[_packet_len] = { 0x7E };
//	this->serial->readBytes(ack + 1, _packet_len - 1);
//
//	if (ack[1] != 0xFF || ack[2] != 0x06 || ack[9] != 0xef) {
//		return;
//	}
//
//
//	int ret = ack[5] << 8 | ack[6];
//	sprintf(buff, "ack: %d,ret: %d", ack[3], ret);
//	LOG_DEBUG(buff)
}
void MiniMp3Service::setEQ(MimiMp3EQ eq) {
	this->send(EQ, eq);
}
void MiniMp3Service::play(uint16_t num) {
	this->send(PLAY, num);
}
void MiniMp3Service::startMusic() {
	this->send(VOLUME, 22);
	this->send(NEXT);
}
void MiniMp3Service::stopMusic() {
	this->send(STOP);
}
void MiniMp3Service::pauseMusic() {
	this->send(PAUSE);
}
void MiniMp3Service::setVolume(uint8_t value) {
	this->send(VOLUME, value);
}
void MiniMp3Service::prepare0() {
	delay(500);
	Serial.println("MiniMp3 open");
	this->serial = &Serial1;
	this->serial->begin(9600, SERIAL_8N1, _mp3_rx, _mp3_tx);
	startMusic();
}
void MiniMp3Service::close() {
	if (this->serial == nullptr)
		return;
	this->serial->end();
}
